# FVG定义：牛市或熊市中连续三只上涨的阳线或阴线，牛市中第一支蜡烛的上影线与第三只蜡烛的下影线不重合，熊市中第一支蜡烛的下影线与第三只蜡烛的上影线不重合 使用python yfinance matplot 构建可视化实现

# FVG 信号入场 没有目标FVG不入场 止损点太远不入场 没有MSS不入场
# Bear: 止损在第一根高点(OB)
# 止盈在下面 FVG 50% 处
# Bull: 止损在第一根低点(OB)
# 止盈在上面 FVG 50% 处
# 1H FVG ALERT

import time
from datetime import datetime
import numpy as np
import pandas as pd
import pytz
import schedule
from BarkNotificator import BarkNotificator
from binance.spot import Spot
from binance.um_futures import UMFutures

# 3. 时间戳转换（含时区处理）


def format_time(timestamp):
    tz = pytz.timezone("Asia/Shanghai")
    return datetime.fromtimestamp(timestamp, tz).strftime("%Y-%m-%d %H:%M:%S")


def convert_to_beijing_time(ts):
    tz = pytz.timezone("Asia/Shanghai")
    return datetime.fromtimestamp(ts // 1e3, tz)


btc = "BTCUSDC"
bnb = "BNBUSDC"
# symbol = "ETHUSDT"

# key = "FC9r3f44u9UgPqnG5wzmW1FlTdUrzu8Bu1G3R18kyv1HdtNo7FedLgsuS3oo6bLH"
# secret = "fjRHyLILCVw0uj29mFTribS94xeFw35SJXjYpkoCsEybPSFeOdrqyBgdzKZkGSBc"

# region limited
# 连续合约K线数据


def get_futures_continous_data(symbol="BTCUSDT", interval="15m", limit="4"):
    um_futures_client = UMFutures()
    klines = um_futures_client.klines(symbol, interval, limit=limit)

    # 2. 转换为结构化数据
    df = pd.DataFrame(
        klines,
        columns=[
            "Open Time",
            "Open",
            "High",
            "Low",
            "Close",
            "Volume",
            "Close Time",
            "Quote Asset Volume",
            "Number of Trades",
            "Taker Buy Base",
            "Taker Buy Quote",
            "Ignore",
        ],
    )

    df["Time"] = df["Open Time"].apply(convert_to_beijing_time)

    # # 4. 构建OHLC数据框架
    ohlc = df.copy()
    ohlc = ohlc.set_index("Time").astype(float)  # 确保数值类型正确

    return ohlc


def get_data(symbol="BTCUSDT", interval="15m", limit="4"):
    # 1. 获取K线原始数据
    # client = Spot(base_url="https://data-api.binance.vision")
    client = Spot(base_url="https://data-api.binance.vision")
    # interval 1s, 1m, 5m, 1h, 1d,
    # 1125-1216 1732475182000-1734289582000 震荡
    # 1106-1125 1730833582000-1732475182000 上涨
    # 0124 1737659180000
    klines = client.klines(
        symbol=symbol,
        interval=interval,
        limit=limit,
        # startTime="1741276800000",  # 2025-03-07 00:00:00+08:00
        # startTime="1730833582000",
        # startTime="1737659180000",
        # startTime="1730833582000",
        # startTime="1732475182000",
        # endTime="1734289582000",
    )  # 示例：BTC/USDT 1小时K线

    # 2. 转换为结构化数据
    df = pd.DataFrame(
        klines,
        columns=[
            "Open Time",
            "Open",
            "High",
            "Low",
            "Close",
            "Volume",
            "Close Time",
            "Quote Asset Volume",
            "Number of Trades",
            "Taker Buy Base",
            "Taker Buy Quote",
            "Ignore",
        ],
    )

    df["Time"] = df["Open Time"].apply(convert_to_beijing_time)

    # # 4. 构建OHLC数据框架
    ohlc = df.copy()
    ohlc = ohlc.set_index("Time").astype(float)  # 确保数值类型正确
    # print(ohlc)
    return ohlc

# 识别FVG模式


def detect_fvg(df):
    fvg_bull = []
    fvg_bear = []
    print(df)
    df = df[:-1]
    print(df)
    for i in range(len(df)-2):
        # 三根连续K线
        c1, c2, c3 = df.iloc[i], df.iloc[i+1], df.iloc[i+2]
        # print(c1,c2,c3)
        # 牛市FVG条件
        bull_cond = (
            # (c1.Close > c1.Open) &
            (c2.Close > c2.Open) & (c3.Close > c3.Open) &  # 三连阳
            (c1.High < c3.Low)  # 上影线与下影线无重叠
        )
        # 熊市FVG条件
        bear_cond = (
            # (c1.Close < c1.Open) &
            (c2.Close < c2.Open) & (c3.Close < c3.Open) &  # 三连阴
            (c1.Low > c3.High)  # 下影线与上影线无重叠
        )

        if (bull_cond):
            fvg_bull.append((c1.name, c3.name, c1.High, c3.Low))
        elif (bear_cond):
            fvg_bear.append((c1.name, c3.name, c3.High, c1.Low))

    return fvg_bull, fvg_bear


if __name__ == "__main__":
    push_key = "5e926333c83d7bb5c9e65e2550ed9684e7d1357daa0f8d7cf865b57439c0aed0"

    def bark_push(title, content):
        bark = BarkNotificator(device_token=push_key)
        bark.send(title=title, content=content,
                  ringtone='minuet.caf', call='1')

    def job(interval, symbol):
        time.sleep(7)
        df = get_futures_continous_data(symbol=symbol, interval=interval)
        fvg_bull, fvg_bear = detect_fvg(df)
        time_at = format_time(time.time())
        print(time_at, fvg_bull, fvg_bear)
        trend = "Long"
        high = 0
        low = 0
        push = False
        if len(fvg_bull) > 0:
            trend = "Long"
            high = fvg_bull[0][3]
            low = fvg_bull[0][2]
            push = True
        if len(fvg_bear) > 0:
            trend = "Short"
            high = fvg_bear[0][3]
            low = fvg_bear[0][2]
            push = True
        # 1h fvg detected bull/bear high: low
        if push:
            title = f"{symbol} {interval} fvg detected"
            content = f"{time_at}\n\n{trend}\n\nHigh:{high}\n\nMid:{np.mean([high, low])}\n\nLow:{low}\n\nStrong?\n\nMSS?\n\nOB?"
            bark_push(title=title, content=content)

    # Run job every hour at the 00nd minute
    interval = "1h"
    schedule.every().hour.at(":00").do(job, interval, btc)
    # schedule.every().hour.at(":00").do(job, interval, bnb)

    interval = "30m"
    schedule.every().hour.at(":00").do(job, interval, btc)
    schedule.every().hour.at(":30").do(job, interval, btc)

    interval = "15m"
    job(interval, btc)

    def job_15m():
        schedule.every().hour.at(":00").do(job, interval, btc).tag("15m")
        schedule.every().hour.at(":15").do(job, interval, btc).tag("15m")
        schedule.every().hour.at(":30").do(job, interval, btc).tag("15m")
        schedule.every().hour.at(":45").do(job, interval, btc).tag("15m")

    def clear_15m():
        schedule.clear("15m")

    schedule.every().day.at('16:00:00').do(job_15m)
    schedule.every().day.at('02:00:00').do(clear_15m)

    while True:
        schedule.run_pending()
        time.sleep(1)

# pm2 start fvg.py --time --interpreter /root/proj/backtester/.venv/bin/python3
